package asiento;

import java.math.BigDecimal;
import java.util.Date;

import org.uqbar.commons.utils.Observable;

import ubicacionEnAvion.UbicacionEnAvion;
import usuario.Usuario;
import vuelo.Vuelo;
import aerolinea.Aerolinea;
import claseAsiento.ClaseAsiento;
import excepciones.NoPuedeComprarException;
import excepciones.NoPuedeReservarException;

@Observable
public class Asiento {
	
	private String codigoAsiento;
	private String numeroAsiento;
	private BigDecimal precio;
	private BigDecimal tiempoDeVuelo;
	private ClaseAsiento claseAsiento;	
	private UbicacionEnAvion ubicacionEnAvion;
	//private Hora	
	//private Horadd
	private Vuelo vuelo;
	private EstadoAsiento estado;
	private String origen;
	private String destino;
	private Date fechaSalida;
	private Date fechaLlegada;
	
	public void setCodigoAsiento(String codigoAsiento) {
		this.codigoAsiento = codigoAsiento;
	}
	
	public String getCodigoAsiento() {
		return codigoAsiento;
	}
	
	public void setPrecio(BigDecimal precio) {
		this.precio = precio;
	}
	
	public BigDecimal getPrecio() {
		return precio;
	}
	   
	public void setClaseAsiento(ClaseAsiento claseAsiento){ 
		this.claseAsiento = claseAsiento; 
	}
	
	public ClaseAsiento getClaseAsiento(){ 
		return this.claseAsiento;
	}
	 
	public void setUbicacionEnAvion(UbicacionEnAvion ubicacionEnAvion) {
		this.ubicacionEnAvion = ubicacionEnAvion;
	}
	
	public UbicacionEnAvion getUbicacionEnAvion() {
		return this.ubicacionEnAvion;
	}

	
	public boolean cumpleCondicionesDeSuperOferta() {		
		 
		return ((this.claseAsiento.esPrimeraClase())&&(this.esMenor(this.precio,new BigDecimal("8000")))||(this.claseAsiento.esEjecutiva())&&(this.esMenor(this.precio,new BigDecimal("4000"))));
		
	}

	public boolean esMenor(BigDecimal precio, BigDecimal precioComparacion) {
		
		if(precio.compareTo(precioComparacion)==-1){
			return true;
		}else{
			return false;
		}
	
	}

	public void setTiempoDeVuelo(BigDecimal tiempoDeVuelo) {
		this.tiempoDeVuelo = tiempoDeVuelo;
	}

	public BigDecimal getTiempoDeVuelo() {
		return tiempoDeVuelo;
	}

	public String getOrigen() {
		return origen;
	}

	public void setOrigen(String origen) {
		this.origen = origen;
	}

	public String getDestino() {
		return destino;
	}

	public void setDestino(String destino) {
		this.destino = destino;
	}

	public Date getFechaSalida() {
		return fechaSalida;
	}

	public void setFechaSalida(Date fechaSalida) {
		this.fechaSalida = fechaSalida;
	}

	public Date getFechaLlegada() {
		return fechaLlegada;
	}

	public void setFechaLlegada(Date fechaLLegada) {
		this.fechaLlegada = fechaLLegada;
	}

	public void setNumeroAsiento(String numeroAsiento) {
		this.numeroAsiento = numeroAsiento;
	}

	public String getNumeroAsiento() {
		return numeroAsiento;
	}
	
	public EstadoAsiento reservar(Usuario usuario) throws NoPuedeReservarException{
		EstadoAsiento estadoFinal = null;
		try{
		//TODO mucha de esta logica deberia estar en el estado del asiento, evitar tantos condicionales
		if(this.estado.sePuedeReservar()){
			if(!this.estado.yaEstaReservado()){
				//TODO evitar hablar con extra�os (don't talk strangers)
				this.getVuelo().getAerolinea().reservarAsiento(this, usuario);
				estadoFinal = new Reservado();
				this.setEstado(estadoFinal);
				usuario.agregarReservaAlHistorial(this);				
			}else{
				estadoFinal = new SobreReservado();
			}
		}
		} catch (RuntimeException e){
			throw new NoPuedeReservarException(codigoAsiento);
		}	
		return estadoFinal;
		//TODO tirar excepcion
	}
	
	public EstadoAsiento sobreReservar(Usuario usuario) throws NoPuedeReservarException{
		EstadoAsiento estadoFinal = null;
		try{
			//TODO mucha de esta logica deberia estar en el estado del asiento, evitar tantos condicionales
			if(this.estado.sePuedeReservar()){
				this.estado.reservar(usuario);
				estadoFinal = new SobreReservado();
				this.setEstado(estadoFinal);
				usuario.agregarReservaAlHistorial(this);
			}
		} catch (RuntimeException e){
			throw new NoPuedeReservarException(codigoAsiento);
		}	
		return estadoFinal;
		//TODO tirar excepcion
	}
	
	public void comprar(Usuario usuario) throws NoPuedeComprarException{
		//TODO Tell don't ask (no usen if, pasenle la pelota al estado y que �l se encargue)
//		this.estado.teCompro(usuario);
		if(this.estado.sePuedeComprarElAsiento(usuario)){
			try{
				this.getVuelo().getAerolinea().comprar(this, usuario);
				this.setEstado(new Comprado());
				usuario.agregarCompraAlHistorial(this);
			} catch (RuntimeException e){
				throw new NoPuedeComprarException(codigoAsiento);
				
			}
		}
		//TODO tirar excepcion
	}
	
    public void reservaVencida(){
        if(this.estado.haySobreReserva()){
            this.estado.cambiarReserva();
        }
        this.setEstado(new Disponible());
    }

	public void setVuelo(Vuelo vuelo) {
		this.vuelo = vuelo;
	}

	public Vuelo getVuelo() {
		return vuelo;
	}

	public void setEstado(EstadoAsiento estado) {
		this.estado = estado;
	}

	public EstadoAsiento getEstado() {
		return estado;
	}

	public void setearEstadoADisponible() {
		this.estado = new Disponible();
	}
	
	public Aerolinea getAerolinea(){
		return this.getVuelo().getAerolinea();
	}
	
	public String toString(){
		return this.getNumeroAsiento();
		
	}
}
